from rest_framework import serializers
from goods.models import SKU


class CartSKUSerializer(serializers.ModelSerializer):
    """
    购物车商品数据序列化器
    """
    count = serializers.IntegerField(label='数量')

    class Meta:
        model = SKU
        fields = ('id', 'name', 'default_image_url', 'price', 'count')


class OrderSettlementSerializer(serializers.Serializer):
    """
    订单结算数据序列化器
    """
    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


from .models import OrderInfo,OrderGoods
from decimal import Decimal
from django_redis import get_redis_connection
from django.db import transaction


class CreateOrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    def create(self, validated_data):
        """
         1. 要生成一个订单id(年月日时分秒+8位user_id)
         2. 获取 user,adress,pay_method数据
         3. 初始化 运费，个数和价格信息
         4. 生成状态信息
         5. 生成订单
         6.从redis中获取商品的数据
         7. 获取选中的数据
         8. 对数据进行遍历
         9. 个数进行一个判断
         10. 修改上坡你的库存和销量
         11.订单的个数和价格累加
         12. 订单商品信息入库
         ** 保存商品信息必须基于已经保存订单，因为商品信息中有外键关联
        """
        user = self.context['request'].user
        from django.utils import timezone
        order_id = timezone.now().strftime('%Y%m%d%H%M%S%f') + '%08d' % user.id
        address = validated_data.get('address')
        total_count = 0
        total_amount = Decimal('0')
        freight = Decimal('10.0')
        pay_method = validated_data.get('pay_method')
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        with transaction.atomic():
            try:
                # 创建保存点
                save_id = transaction.savepoint()
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=total_count,
                    total_amount=total_amount,
                    freight=freight,
                    pay_method=pay_method,
                    status=status,
                )
                redis_conn = get_redis_connection('cart')
                redis_cart = redis_conn.hgetall('cart_%s'%user.id)
                redis_selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)
                cart = {}
                for sku_id in redis_selected_ids:
                    cart[int(sku_id)] = int(redis_cart[sku_id])
                for sku_id,count in redis_cart.items():
                    sku = SKU.objects.get(pk=sku_id)
                    count = int(count)
                    if count > sku.stock:
                        # 回滚到保存点
                        transaction.savepoint_rollback(save_id)
                        raise serializers.ValidationError('库存不足')
                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()
                    # 模拟并发
                    import time
                    time.sleep(5)
                    old_stock = sku.stock

                    new_stock = sku.stock - count
                    new_sales = sku.sales + count
                    # 判断库存是否更新，若更新，表示下单失败
                    rect = SKU.objects.filter(pk=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)
                    if rect == 0:
                        raise serializers.ValidationError('下单失败')
                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=count,
                        price=sku.price,
                    )
            except Exception:
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError('下单失败')
            else:
                order.save()
                # 提交从保存点到当前状态的所有数据库事务操作
                transaction.savepoint_commit(save_id)
        return order
